home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
dpmigcc5.zip
/
RSX
/
SOURCE
/
DEB
/
DEB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-12
|
14KB
|
674 lines
/*
** Debugger with ptrace()
**
** (c) Rainer Schnitker 1994
*/
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "ansi.h"
#ifdef __GO32__
#include <sys\_process.h>
#include <sys\_ptrace.h>
#include <sys\_user.h>
#include <sys\_reg.h>
#include <sys\_signal.h>
#else
#include <process.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <signal.h>
#endif
#include "syms.h"
#include "unassmbl.h"
#include "breakp.h"
#include "dpmi.h"
#include "ansi.h"
extern int get_input(char *, int, int);
static int pid;
static int uaddr;
static char **org_env;
static int sigtrap;
struct reg_names {
char *name;
int size;
int ofs;
};
extern struct reg_names regs[];
typedef enum {
Unknown,
CONT,
STEP,
NEXT,
LIST,
DUMP,
DISP,
SHELL,
BREAK_SET, BREAK_LIST, BREAK_CLEAR, BREAK_ENABLE, BREAK_DISABLE,
REGS,
SET,
WHERE,
FIND,
NPX,
PROCESS,
USER,
SEL,
HELP,
QUIT
} deb_commands;
typedef struct {
char *cp;
deb_commands t;
} item;
static item cmds[] =
{
"go", CONT, "g", CONT,
"cont", CONT, "c", CONT,
"step", STEP, "s", STEP,
"next", NEXT, "n", NEXT,
"list", LIST, "l", LIST,
"dump", DUMP, "d", DUMP,
"disp", DISP,
"reg", REGS, "r", REGS,
"where", WHERE, "w", WHERE,
"find", FIND, "f", FIND,
"bp", BREAK_SET,
"bc", BREAK_CLEAR,
"bd", BREAK_DISABLE,
"be", BREAK_ENABLE,
"bl", BREAK_LIST,
"set", SET,
"process", PROCESS,
"user", USER,
"shell", SHELL,
"sel", SEL,
"npx", NPX,
"help", HELP, "h", HELP, "?", HELP,
"quit", QUIT, "q", QUIT,
0, 0
};
char *sig_text[] =
{
NULL,
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGABRT",
"SIGEMT",
"SIGFPE",
"SIGKILL",
"SIGBUS",
"SIGSEGV",
"SIGSYS",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"16"
"17"
"SIGCLD",
"19"
"20"
"SIGBREAK"};
static ansi_flag=0;
void ansi(int fg)
{
if (!ansi_flag)
return;
printf("\033[%d;%dm", (fg & A_bold) ? 1 : 0, 30+(fg&7));
}
void read_memory(unsigned long addr, BYTE *buf, int len)
{
unsigned long long pc, r, i;
for (pc = addr, i = 0; pc < addr + len; pc++, i++) {
errno = 0;
r = ptrace(PTRACE_PEEKDATA, pid, pc, 0);
if (errno != 0)
break;
else
buf[i] = (BYTE) r&0xff;
}
}
int ptrace_get_register(int off)
{
int r;
errno = 0;
r = ptrace(PTRACE_PEEKUSER, pid, uaddr + off, 0);
if (r == -1 && errno)
perror("ptrace");
return r;
}
int ptrace_put_register(int off, long value)
{
int r;
errno = 0;
r = ptrace(PTRACE_POKEUSER, pid, uaddr + off, value);
if (r == -1 && errno)
perror("ptrace");
return r;
}
static void show_regs(void)
{
static int seg_no[6] = { CS, DS, ES, SS, FS, GS };
static char * seg_name[6] = { "cs", "ds", "es", "ss", "fs", "gs" };
int i, r, j = 1;
for (i = 0; i <= 9; ++i) {
errno = 0;
r = ptrace_get_register(regs[i].ofs * 4);
if (errno != 0) {
perror("ptrace");
return;
}
if (++j == 4) {
j = 0;
putchar('\n');
}
printf("%s=%.8x ", regs[i].name + 1, r);
}
putchar('\n');
for (i = 0; i <= 5; ++i) {
errno = 0;
r = ptrace_get_register(seg_no[i] * 4);
if (errno != 0) {
perror("ptrace");
return;
}
printf("%s=%.4x ", seg_name[i], r & 0xFFFF);
}
putchar('\n');
}
static int do_run(int cmd)
{
int s, t, p, r;
s = ptrace(cmd, pid, 0, 0);
if (s < 0) {
perror("ptrace");
return 0;
}
p = wait(&t);
if (p == -1)
perror("wait");
if ((t & 0377) != 0177) {
printf("Program terminated (%d)\n", (t >> 8) & 0xff);
exit(0);
}
else {
if ((t >> 8) == SIGTRAP)
sigtrap = 1;
else {
printf("process %p stopped by signal %s\n", p, sig_text[t >> 8]);
sigtrap = 0;
}
}
errno = 0;
r = ptrace_get_register(EIP * 4);
if (errno != 0) {
perror("ptrace");
return 0;
}
return r;
}
static int run(int cmd)
{
int i, r, t;
if (cmd == PTRACE_STEP)
return do_run(PTRACE_STEP);
/* RESUME, if breakpoint at eip, do one step */
r = ptrace_get_register(EIP * 4);
for (i = 0; i < MAX_BP; ++i)
if (bp[i].addr == r && bp[i].status == BP_ENABLE)
break;
if ((i < MAX_BP) &&
(ptrace(PTRACE_PEEKTEXT, pid, r, 0) & 0xFF) != 0xCD)
do_run(PTRACE_STEP);
insert_breakpoints(pid);
r = do_run(PTRACE_RESUME);
remove_breakpoints(pid);
/* correct eip, take back 1 step */
if (r) {
r -= sigtrap;
ptrace(PTRACE_POKEUSER, pid, uaddr + EIP * 4, r);
}
return r;
}
static void dump(unsigned long n)
{
static unsigned long dump_addr;
int i, j;
BYTE dump_buf[16];
if (n)
dump_addr = n;
if (dump_addr == 0)
return;
for (i = 0; i < 8; ++i) {
printf("%08lx: ", dump_addr);
for (j = 0; j < 16; j++) {
dump_buf[j] = (BYTE) ptrace(PTRACE_PEEKDATA, pid, dump_addr++, 0);
printf("%02X ", dump_buf[j] & 0xFF);
}
putchar(' ');
for (j = 0; j < 16; ++j) {
char c = dump_buf[j];
if (isalnum(c) || ispunct(c))
putchar(c);
else
putchar('.');
}
putchar('\n');
}
}
static void command_loop(void)
{
static unsigned long next_inst;
static unsigned long this_inst;
static int cmd;
static char prompt[] = "cmd:";
unsigned long temp, list_inst;
int i, j, len;
char input[40];
char *argv[10];
char *name;
putchar('\n');
show_regs();
list_inst = this_inst = ptrace_get_register(EIP * 4);
next_inst = unassemble(this_inst, 1);
while (1) {
ansi(A_white);
printf("%s", prompt);
fflush(stdout);
len = get_input(input, 40, 0);
ansi(A_yellow);
/* make strings */
j = 0;
for (i = 0; input[i] != 0; i++)
if (input[i] == ' ') {
input[i] = 0;
if (input[i + 1] == ' ')
continue;
if (input[i + 1] == 0)
continue;
argv[j++] = input + i + 1;
}
argv[j] = 0;
if (*input == 0) { /* only return */
for (i = sizeof(prompt); i != 0; i--) {
putchar('\b'), putchar(' '), putchar('\b');
fflush(stdout);
argv[0] = NULL;
}
} else { /* new input */
putchar('\n');
fflush(stdout);
list_inst = this_inst;
for (i = 0; cmds[i].cp; i++)
if (strcmp(cmds[i].cp, input) == 0) {
cmd = cmds[i].t;
i = -1;
break;
}
if (i != -1 && *input)
cmd = Unknown;
}
switch (cmd) {
case HELP:
printf("go <v> g - go or continue execution\n");
printf("cont <v> c - continue execution\n");
printf("step s - step through instruction\n");
printf("next n - step to next instruction\n");
printf("list <v> l - list instructions at <v>\n");
printf("dump <v> d - dump memory at <v>\n");
printf("disp v - display symbol v\n");
printf("reg <m> <v> r - show/set registers\n");
printf("where w - display list of active functions\n");
printf("find f - find a symbol/location (wildcard)\n");
printf("bp v - set breakpoint at v\n");
printf("bx no - x=List/Clear/Dis-/Enable breakpoint no\n");
printf("set m v <s> - memory to value; size=byte/word\n");
printf("process - show process data\n");
printf("sel s <n> - show n selectors start with s\n");
printf("shell argv - execute other program\n");
printf("quit q - terminate debugger\n");
printf("help ? - this text\n");
break;
case CONT:
if (argv[0]) {
temp = syms_name2val(argv[0]);
if (undefined_symbol)
break;
i = set_bp(temp);
run(PTRACE_RESUME);
delete_bp(i);
} else
run(PTRACE_RESUME);
break;
case STEP:
if ((ptrace(PTRACE_PEEKTEXT, pid, this_inst, 0) & 0xFF) == 0xCD)
goto Next; /* not INT instr */
run(PTRACE_STEP);
break;
case NEXT:
if (last_unassemble_unconditional || last_unassemble_jump)
run(PTRACE_STEP);
else {
Next:
i = set_bp(next_inst);
run(PTRACE_RESUME);
delete_bp(i);
}
break;
case LIST:
if (argv[0]) { /* weitere eingabe */
temp = syms_name2val(argv[0]);
if (!undefined_symbol)
list_inst = temp;
else
list_inst = this_inst;
}
for (i = 1; i <= 10; i++)
list_inst = unassemble(list_inst, 0);
break;
case DUMP:
if (argv[0] == NULL) {
dump(0);
break;
}
else
temp = syms_name2val(argv[0]);
if (!undefined_symbol) {
printf("%s: adr 0x%08x val 0x%08lx\n", argv[0], temp,
ptrace(PTRACE_PEEKDATA, pid, temp, 0));
dump(temp);
}
break;
case DISP:
if (!argv[0])
break;
temp = syms_name2val(argv[0]);
if (!undefined_symbol)
printf("%s: adr 0x%08x val 0x%08lx\n", argv[0], temp,
ptrace(PTRACE_PEEKDATA, pid, temp, 0));
break;
case BREAK_SET:
if (argv[0]) {
temp = syms_name2val(argv[0]);
if (undefined_symbol)
break;
i = set_bp(temp);
if (i>0)
printf("breakpoint %d set\n",i);
}
break;
case BREAK_CLEAR:
if (argv[0]) {
sscanf(argv[0], "%d", &i);
delete_bp(i);
}
break;
case BREAK_ENABLE:
if (argv[0]) {
sscanf(argv[0], "%d", &i);
enable_bp(i);
}
break;
case BREAK_DISABLE:
if (argv[0]) {
sscanf(argv[0], "%d", &i);
disable_bp(i);
}
break;
case BREAK_LIST:
printf("Breakpoint list:\n");
for (i = 0; i < MAX_BP; i++)
if (bp[i].status) {
name = syms_val2name(bp[i].addr, &temp);
printf("bp %d at %08X ", i, bp[i].addr);
if (name)
printf("%s", name);
if (temp)
printf("+%lX ", temp);
if (bp[i].status == BP_DISABLE)
printf(" - disabled");
printf("\n");
}
break;
case REGS:
if (argv[0] == NULL) {
show_regs();
break;
}
if (argv[1] == NULL)
break;
temp = syms_name2val(argv[1]);
if (undefined_symbol)
break;
j = 0;
for (i = 0; regs[i].name; i++)
if (strcmp(regs[i].name, argv[0]) == 0) {
int r = ptrace_get_register(regs[i].ofs * 4);
j=1;
switch (regs[i].size) {
case 0:
r = (r & 0xffff00ff) | ((temp & 0xff) << 8);
break;
case 1:
* (char *) & r = * (char *) & temp;
break;
case 2:
* (short *) & r = * (short *) & temp;
break;
case 4:
r = temp;
break;
}
ptrace_put_register(regs[i].ofs * 4, r);
break;
}
if (!j)
puts("register not found");
break;
case SHELL:
if (argv[0] == NULL)
break;
if (spawnvpe(P_WAIT, argv[0], argv, org_env) < 0)
printf("error spawn %s\n", argv[0]);
break;
case FIND:
if (argv[0] == NULL)
break;
if (strpbrk(argv[0], "*?") != NULL) {
syms_listwild(argv[0]);
break;
}
temp = syms_name2val(argv[0]);
if (!undefined_symbol) {
name = syms_val2name(this_inst, &temp);
printf("0x%08lx %s", this_inst, name);
if (temp)
printf("+%lx", temp);
name = syms_val2line(this_inst, &i, 0);
if (name)
printf(", line %d in file %s", i, name);
putchar('\n');
}
break;
case SET:
if (argv[0] == NULL || argv[1] == NULL)
break;
if (*(argv[0]) == '%') {
puts("Use the command 'reg' or 'r'");
break;
}
else {
DWORD pokeat;
int size;
temp = syms_name2val(argv[1]);
if (undefined_symbol)
break;
pokeat = syms_name2val(argv[0]);
if (undefined_symbol)
break;
if (argv[2]) {
if (*(argv[2]) == 'b')
size = 1;
else if (*(argv[2]) == 'w')
size = 2;
} else
size=0;
if (size) { /* value */
DWORD oldv = ptrace(PTRACE_PEEKTEXT, pid, pokeat, 0);
if (size = 1)
* (char *) & temp = * (char *) & temp;
else
* (short *) & temp = * (short *) & temp;
}
ptrace(PTRACE_POKETEXT, pid, pokeat, temp);
}
break;
case PROCESS:
printf("pid %d ppid %d\n\n", getpid(), getppid());
PrintFreeMemInfo();
break;
case SEL:
if (argv[0] == NULL)
break;
if (argv[1] == NULL)
i = 1;
else
i = atoi(argv[1]);
temp = syms_name2val(argv[0]);
if (undefined_symbol)
break;
show_descriptor(temp, i);
break;
case QUIT:
ansi(A_white);
return;
case Unknown:
printf("unknown command, try (H)elp or ?\n");
break;
} /* switch */
if (cmd == CONT || cmd == NEXT || cmd == STEP) {
list_inst = this_inst = ptrace_get_register(EIP * 4);
next_inst = unassemble(this_inst, 1);
}
} /* while */
}
int main(int argc, char **argv, char **envp)
{
static char debug_file[260];
struct user u;
char *term;
term = getenv("TERM");
if (term != NULL && strncmp(term, "ansi", 4) == 0) {
ansi_flag = 1;
}
org_env = envp;
if (argv[1])
strcpy(debug_file, argv[1]);
for (;;) {
if (access(debug_file, 0) < 0)
strcat(debug_file, ".exe");
pid = spawnvpe(P_DEBUG | P_WINDOWED, debug_file, argv + 1, envp);
if (pid < 0) {
perror("Debugger spawnve");
printf("New Filename:");
gets(debug_file);
}
else
break;
}
printf("child PID %d\n", pid);
errno = 0;
uaddr = ptrace(PTRACE_PEEKUSER, pid, (char *) &u.u_ar0 - (char *) &u, 0);
if (errno != 0)
perror("ptrace");
uaddr -= 0xe0000000;
printf("debugging file %s\n", debug_file);
fflush(stdout);
syms_init(debug_file);
command_loop();
return (0);
}